package me.zhenqu.services;

import me.zhenqu.model.bo.StatusBo;
import me.zhenqu.model.bo.TimeLineBo;
import me.zhenqu.model.bo.UserBo;
import me.zhenqu.model.pojo.entity.Status;
import me.zhenqu.model.pojo.entity.StatusCount;
import me.zhenqu.model.pojo.entity.TimeLine;
import me.zhenqu.model.pojo.entity.User;
import me.zhenqu.services.cache.AbstractCache;
import me.zhenqu.services.cache.CacheMaker;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: yibing.tan
 * Date: 11-11-10
 * Time: 下午4:41
 * To change this template use File | Settings | File Templates.
 */
public class StatusService {
    @Autowired
    CacheMaker cacheMaker;
    @Autowired
    StatusBo statusBo;

    @Autowired
    UserBo bo;

    @Autowired
    TimeLineBo timeLineBo;

    public UserBo getBo() {
        return bo;
    }

    public void setBo(UserBo bo) {
        this.bo = bo;
    }

    public void setCacheMaker(CacheMaker cacheMaker) {
        this.cacheMaker = cacheMaker;
    }

    public void setStatusBo(StatusBo statusBo) {
        this.statusBo = statusBo;
    }

    public void setTimeLineBo(TimeLineBo timeLineBo) {
        this.timeLineBo = timeLineBo;
    }

    public void publish(Status status){
        statusBo.save(status);
        if (!status.isIs_comment()){
            cacheMaker.saveStatus(status);
            CommonService.createTimeLine(status, bo, timeLineBo);
        }
    }

    public void delete(Long status_id) {
        delete(getById(status_id));
    }

    private void delete(Status status) {
        statusBo.delete(status);
        cacheMaker.deleteStatus(status);
        deleteTimeLine(status);
    }

    private void deleteTimeLine(Status status) {
        List<Long> followed = bo.loadFollowedUserIds(status.getUser_id());
        if (followed==null||followed.isEmpty()) return;
        TimeLine tl = null;
        long sid = status.getStatus_id();
        for (Long user_id: followed){
            tl = new TimeLine();
            tl.setUser_id(user_id);
            tl.setStatus_id(sid);
            timeLineBo.delete(tl);
        }
    }

    public List<Status> getStatus(Long user_id, long since){
        String uidStatusSet = cacheMaker.makeKey(CacheMaker.USERSTATUS,user_id);
        Collection<String> keys = cacheMaker.getAllIdsFromCache(uidStatusSet);
        List<Status> statuses = new LinkedList<Status>();
        if (keys==null||keys.isEmpty()){
            statuses =  statusBo.findUserStatusSince(user_id, since);
            cacheMaker.initStatues(statuses);
            return statuses;
        }
        AbstractCache cache = cacheMaker.getCache();

        for (String cukey: keys){
            Status status = (Status)cache.get(cukey);
            if (status==null){
                Long status_id = cacheMaker.unformat(cukey);
                if (status_id==null) continue;
                status = getById(status_id);
                if (status==null) {
                    String key = cacheMaker.makeKey(CacheMaker.StatusTag, status_id);
                    cacheMaker.deleteFromSet(uidStatusSet, key);
                    continue;
                }
            }
            statuses.add(status);
        }
        return statuses;
    }

    public List<Status> getUserTimeLines(Long user_id, long since){
        List<TimeLine> timeLineList = timeLineBo.loadTimeLines(user_id, since);
        List<Status> mineList = new LinkedList<Status>();
        mineList.addAll(getStatus(user_id, since));
        if (timeLineList==null||timeLineList.isEmpty()) return mineList;
        for (TimeLine current: timeLineList){
            long status_id = current.getStatus_id();
            Status st = getById(status_id);
            if (st==null) continue;
            mineList.add(st);
        }
        Collections.sort(mineList, new ByValueItemComparator());
        return mineList;
    }

    public Status getById(Long status_id){
        Status existent = cacheMaker.getStausFromCache(status_id);
        if (existent!=null) return existent;
        existent = statusBo.findByID(status_id);
        if (existent!=null)
            cacheMaker.saveStatus(existent);
        return existent;
    }

    public void retweet(User user, Long status_id, String text, boolean comment){
        Status st = new Status();
        st.setUser_id(user.getUser_id());
        st.setUser_name(user.getNick_name());
        st.setPubtime(new Date());
        st.setIn_reply_status_id(status_id);
        st.setText(text);
        st.setIs_comment(comment);
        publish(st);
        statusBo.add1StatusCount(status_id, comment);
    }

    public List<Status> getComments(Status currentStatus){
        return statusBo.findCommentStatusSince(currentStatus,0);
    }

    public StatusCount getStatusCount(Long status_id){
        StatusCount current = statusBo.getStatusCount(status_id);
        if (current==null)
            current = getDefault(status_id);
        return current;
    }

    public StatusCount getDefault(Long status_id) {
        StatusCount aDefault = new StatusCount();
        aDefault.setStatus_id(status_id);
        return aDefault;
    }

    static class ByValueItemComparator implements Comparator<Status>, Serializable {
        @Override
        public int compare(Status s1, Status s2) {
            long time1 = s1.getPubtime().getTime();
            long time2 = s2.getPubtime().getTime();
            if (time1 > time2)
                return -1;
            else if (time1 < time2)
                return 1;
            else
                return 0;
        }
    }
}
